/*! 
 * Interface file for a generic physical entity.
 *
 * \author Devis Rossini
 * \date 19 March 2012
 */
#ifndef PHXCOLLISIONPRIMITIVE_H_INCLUDE_GUARD
#define PHXCOLLISIONPRIMITIVE_H_INCLUDE_GUARD

#include "PhxCore.h"
#include "PhxRigidBody.h"
#include "PhxCollisionPrimitiveDescriptor.h"

#include "PhxCollisionPrimitiveAttributes.h"

namespace phx
{
    /*!
     * Represents a primitive to detect collisions against.
     */
    class CollisionPrimitive
    {
	protected:

        /*!
         * The rigid body that is represented by this primitive.
         */
        RigidBody* mBody;

        /*!
         * The offset of this primitive from the given rigid body.
         */
        Matrix4 mOffset;

		/*!
         * The resultant transform of the primitive. This is
         * calculated by combining the offset of the primitive
         * with the transform of the rigid body.
         */
        Matrix4 mTransform;

		// Useful shortcuts.
		typedef CollisionPrimitiveAttribute			Attribute;
		typedef CollisionPrimitiveAttributesManager AttributesManager;

		/*!
		 * Attributes manager for the collision primitive.
		 */ 
		AttributesManager mAttributesManager;

		/*!
		 * Constructor.
		 */
		CollisionPrimitive() : mBody(0) { }

		/*!
		 * Constructor (with descriptor).
		 */
		CollisionPrimitive(const CollisionPrimitiveDescriptor& desc)
			: mBody(0) 
		{
			mBody = new RigidBody(desc);
			CalculateTransform();
		}

	public:

		/*! 
		 * Primitive's shape type.
		 */
		virtual inline ShapeTypes GetShapeType() const { return NO_SHAPE; }

		/*! 
		 * Primitive's rigid body.
		 */
		inline RigidBody* GetBody() const
		{
			return mBody;
		}

		/*!
         * Calculates the resultant transform for the primitive.
         */
        void CalculateTransform();

        /*!
         * Allow access to the axis vectors in the transform 
		 * for this primitive.
         */
        inline Vector3 GetAxis(unsigned index) const
        {
            return mTransform.GetAxisVector(index);
        }

        /*!
         * Returns the resultant transform of the primitive, calculated from
         * the combined offset of the primitive and the transform
         * (orientation + position) of the rigid body to which it is
         * attached.
         */
        inline const Matrix4& GetTransform() const
        {
            return mTransform;
        }

		/*! 
		 * Set a new attribute or change the status of a specified one.
		 */
		inline void SetAttribute(const Attribute iAttribute, const bool iAcitve)
		{
			mAttributesManager.SetAttribute(iAttribute, iAcitve);
		}

		/*!
		 * Return true if the body has a specified attribute.
		 */
		inline bool HasAttribute(const Attribute iAttribute) const
		{
			return mAttributesManager.HasAttribute(iAttribute);
		}

		/*!
		 * Destructor (virtual).
		 */
		virtual ~CollisionPrimitive() { }
    };
}

#endif // PHXCOLLISIONPRIMITIVE_H_INCLUDE_GUARD